#include "DList.h"

template <typename T>
DList<T>::DList(void) : first(NULL), last(NULL), size(0)
{

}

template <typename T>
DList<T>::DList(const DList<T>& that) : first(NULL), last(NULL), size(0)
{
	*this = that;
}

template <typename T>
DList<T>::~DList(void)
{
	RemoveAll();
}

template <typename T>
DList<T>& DList<T>::operator=(const DList<T>& that)
{
	RemoveAll();

	if( that.size )
	{
		Node<T>* iter = that.first;
		while(iter)
		{
			AddFront(iter->item);
			iter = iter->next;
		}

		size = that.size;
	}

	return *this;
}

template <typename T>
T& DList<T>::operator[](unsigned int index)
{
	if( index >= size )
		return first->item;

	Node<T>* temp = first;

	for(unsigned int i = 0; i < index; i++)
	{
		if( temp->next )
		{
			temp = temp->next;
		}
	}

	return temp->item;
}

template <typename T>
void DList<T>::AddBack(const T& item)
{
	if( first )
	{
		Node<T>* temp = new Node<T>(item);

		if( first != last )
		{
			temp->next = NULL;
			last->next = temp;
			temp->previous = last;
		}
		else
		{
			first->next = temp;
			temp->next = NULL;
			temp->previous = first;
		}

		last = temp;
	}
	else if( !first )
	{
		first = new Node<T>(item);
		last = first;
	}

	size++;
}

template <typename T>
void DList<T>::AddFront(const T& item)
{
	if( first )
	{
		Node<T>* temp = new Node<T>(item);

		if( first != last )
		{
			temp->previous = NULL;
			first->previous = temp;
			temp->next = first;
		}
		else
		{
			first->previous = temp;
			temp->next = first;
			temp->previous = NULL;
		}

		first = temp;
	}
	else if( !first )
	{
		first = new Node<T>(item);
		last = first;
	}

	size++;
}

template <typename T>
void DList<T>::RemoveBack(void)
{
	if( first )
	{
		Node<T>* temp = last;
		
		if( last == first )
		{
			first = NULL;
			last = NULL;
		}
		else
		{
			last = last->previous;
			last->next = NULL;
		}

		delete temp;

		size--;
	}
}

template <typename T>
void DList<T>::RemoveFront(void)
{
	if( first )
	{
		Node<T>* temp = first;
		
		if( last == first )
		{
			first = NULL;
			last = NULL;
		}
		else
		{
			first = first->next;
			first->previous = NULL;
		}

		delete temp;

		size--;
	}
}

template <typename T>
void DList<T>::RemoveAt(unsigned int index)
{
	if( !first )
		return;

	if( size == 0 || index >= size )
		return;

	Node<T>* temp = first;
	for(unsigned int i = 0; i < index; i++)
	{
		if(temp->next)
			temp = temp->next;
	}

	if( first == last )
	{
		first = NULL;
		last = NULL;
	}
	else
	{
		if( temp == first )
		{
			first = first->next;
			first->previous = NULL;
		}
		else if( temp == last )
		{
			last = last->previous;
			last->next = NULL;
		}
		else
		{
			temp->previous->next = temp->next;
			temp->next->previous = temp->previous;
		}
	}

	delete temp;

	size--;
}

template <typename T>
void DList<T>::RemoveAll(void)
{
	while(first)
	{
		RemoveBack();
	}

	last = NULL;
	size = 0;
}

template <typename T>
unsigned int DList<T>::Size(void)
{
	return size;
}